package api

import (
	"errors"
	"log"
	"time"

	"github.com/golang-jwt/jwt"
)

type TokenOptions struct {
	ID        int    `json:"id"`
	UserName  string `json:"username"`
	ExpiresAt int64
}

type ClaimsInfo struct {
	ID       int    `json:"id"`
	UserName string `json:"username"`
	*jwt.StandardClaims
}

type AuthorizeToken struct {
	tokenSalt []byte
}

func NewAuthorizeToken(secretKey string) *AuthorizeToken {
	if secretKey == "" {
		log.Fatal("secretKey is invalid")
		return nil
	}
	return &AuthorizeToken{
		tokenSalt: []byte(secretKey),
	}
}
func (_this *AuthorizeToken) GetTokenString(options *TokenOptions) string {
	if options.ID == 0 {
		log.Fatal("ID is invalid")
		return ""
	}
	if options.UserName == "" {
		log.Fatal("UserName is invalid")
		return ""
	}
	if options.ExpiresAt == 0 {
		// 60分钟过期失效
		options.ExpiresAt = time.Now().Add(time.Minute * 60).Unix()
	}
	standardClaims := &ClaimsInfo{
		ID:       options.ID,
		UserName: options.UserName,
		StandardClaims: &jwt.StandardClaims{
			ExpiresAt: options.ExpiresAt,
		},
	}
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, standardClaims)
	signedString, error := token.SignedString(_this.tokenSalt)
	if error != nil {
		log.Fatal("getToken is error is invalid")
		return ""
	}
	return signedString
}

func (_this *AuthorizeToken) ParseTokenStirng(tokenString string) (*ClaimsInfo, error) {
	if tokenString == "" {
		return nil, errors.New("token is invalid")
	}
	var claimsInfo ClaimsInfo
	token, error := jwt.ParseWithClaims(tokenString, &claimsInfo, func(token *jwt.Token) (interface{}, error) {
		return _this.tokenSalt, nil
	})
	if _, ok := token.Claims.(*ClaimsInfo); ok && token.Valid {
		return &claimsInfo, nil
	} else {
		return nil, error
	}
}
